package com.hoshino.momochi.controller;

import com.alibaba.fastjson.JSON;
import com.hoshino.momochi.model.DTO.MessageDTO;
import com.hoshino.momochi.model.domain.Message;
import com.hoshino.momochi.service.MessageService;
import com.hoshino.momochi.service.RedisService;
import com.hoshino.momochi.service.SseService;
import com.hoshino.momochi.util.CodeEnum;
import com.hoshino.momochi.util.JsonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
@RestController
public class SseController {

    @Autowired
    private SseService sseService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private RedisService redisService;

    private final String USER_ID = CodeEnum.USERID.getMessage();

    private final String TOKEN_NAME = CodeEnum.TOKEN.getMessage();


    /**
     * SSE 连接
     * 根据用户ID 创建 SSE 连接
     *
     * @param request
     * @return SseEmitter
     */
    @RequestMapping(value = "/api/sse/connect", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter SseConnect(HttpServletRequest request) {
        // 由于 前已经校验用户登录状态 并且 将 用户id 存入 请求中
        // 获取 用户token
        Long uid = (Long) request.getAttribute(USER_ID);
        // 为用户 建立 SSE 连接
        return sseService.connect(uid);
    }

    /**
     * 消息发送
     * 发送失败 要么用户不存在，要么用户离线了 那么首先就要保证有这个用户
     * 在当前结构下，可以 提前获取 用户id最大为多少 以此来避免 错误发送
     * 但是这样就会有另一个问题 单纯请求来看 我可以给任何一个人发送消息只要它存在，不是好友也可以。
     * 此处 现 假设 用户一定存在 ， 也一定允许可以发送消息，那么离线则 直接缓存至 redis即可。
     *
     * @param request
     * @param messageDTO 需求字段 pull_id message
     */
    @RequestMapping("/api/sse/send")
    public JsonResponse SseSendMessage(HttpServletRequest request, @RequestBody MessageDTO messageDTO) {
        Long sendId = (Long) request.getAttribute(USER_ID);
        String message = messageDTO.getMessage();
        messageDTO.setSend_id(sendId);
        List<Long> inputList = messageDTO.getPull_list();
        Long pullId = messageDTO.getPull_id();
        List<Long> pullList = Objects.isNull(inputList) ? new ArrayList<>() : inputList;
        if (Objects.nonNull(pullId)) {
            pullList.add(pullId);
        }

        if (pullList.isEmpty()) {
            return JsonResponse.success(CodeEnum.NOTNULL.getCode(), CodeEnum.NOTNULL.getMessage());
        }

        for (Long pId : pullList) {
            if (sseService.sendMessage(sendId, pId, message)) {
                // 发送成功
                // 会保存到 数据库中
            } else {
                MessageDTO inNeed = new MessageDTO(sendId, pId, message);
                redisService.MessageCache(pId, inNeed);
            }
        }
        return JsonResponse.success(CodeEnum.SUCCESS.getCode(), CodeEnum.SUCCESS.getMessage());
    }

    /**
     * 获取指定用户ID的全部离线消息
     * 数据库中有离线消息 可以弃用该方法
     *
     * @param request
     * @return
     */
    @RequestMapping("api/sse/pull")
    public JsonResponse SsePullMessage(HttpServletRequest request) {
        Long uid = (Long) request.getAttribute(USER_ID);
        List<String> ans = redisService.PullMessage(uid);
        List<MessageDTO> p = new ArrayList<>();
        for (int i = 0; i < ans.size(); i++) {
            MessageDTO m = (JSON.parseObject(ans.get(i), MessageDTO.class));
            p.add(m);
            Message mm = new Message(m.getSend_id(), m.getPull_id(), m.getMessage());
            messageService.addMessage(mm);
        }
        return JsonResponse.success(p, CodeEnum.SUCCESS.getMessage());
    }
}
